# -*- coding: utf-8 -*-
"""
202103
钢板焊接
@author: WZS
"""

import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
import csv
import os
import random
from sklearn.metrics import classification_report
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv1D, MaxPooling1D
from keras.optimizers import SGD


def load_data():
    X = []
    Y = []
    for filename in os.listdir('./data_ann/'):
        file_path = (os.path.join('./data_ann/', filename))
        with open(file_path, newline='') as csvfile:
            data = list(csv.reader(csvfile))
        b = []
        for j in range(1, 221):  # 250):
            a = []
            for i in range(1, 23):  # 25):
                try:
                    if data[j][i] != '':
                        a.append(float(data[j][i]))
                except:
                    a.append(0.0)
                else:
                    pass
            b.append(a)
        X.append(b)
        # if int(data[1][0]) < 80:
        #     Y.append(0)
        # else:
        #     Y.append(1)
    print(np.array(X).shape)
    Y = [0] * 17 + [1] * 26
    print(np.array(Y).shape)

    return X, Y


def normailzed(data):
    data_nor = []
    for xx in data:
        xx = np.array(xx)
        a = xx
        minval = np.min(np.where(a == 0, a.max(), a), axis=0)
        maxval = np.max(np.where(a == 0, a.min(), a), axis=0)
        max_min = maxval - minval
        for i in range(len(max_min)):
            max_min[i] = 10000 if max_min[i] == 0 else max_min[i]
        x_normed = (xx - minval) / max_min
        for i in range(len(xx)):
            for j in range(len(xx[i])):
                if xx[i][j] == 0:
                    x_normed[i][j] = 0.0
        data_nor.append(x_normed.tolist())
    return data_nor


def MLP(x_train, y_train, x_test, y_test):
    print(np.array(x_train).shape)
    x_train = np.array(x_train).reshape((30, 220 * 22)).tolist()
    print(np.array(x_train).shape)
    print(np.array(x_test).shape)
    x_test = np.array(x_test).reshape((13, 220 * 22)).tolist()
    print(np.array(x_test).shape)
    # MLP
    model = Sequential()
    # model.add(Dense(64, input_shape=(220, 22), activation='relu'))

    model.add(Dense(64, input_dim=220 * 22, activation='relu'))
    # Drop防止过拟合的数据处理方式
    model.add(Dropout(0.5))

    model.add(Dense(64, activation='relu'))
    model.add(Dropout(0.5))

    model.add(Flatten())
    model.add(Dense(1, activation='sigmoid'))
    # 编译模型，定义损失函数、优化函数、绩效评估函数

    model.compile(loss='binary_crossentropy',
                  optimizer='rmsprop',
                  metrics=['accuracy'])
    # 导入数据进行训练
    model.fit(x_train, y_train,
              epochs=300,
              batch_size=30)
    # 模型评估
    # score = model.evaluate(x_test, y_test, batch_size=1)
    # print(score)

    num = 0
    y_pred = model.predict(x_test)
    for i in range(len(y_pred)):
        y_pred[i] = round(y_pred[i][0])
        if y_pred[i] == y_test[i]:
            num = num + 1
    acc = num / len(y_pred)
    print(model.summary())
    return acc


def Conv_test(x_train, y_train, x_test, y_test):
    model = Sequential()

    model.add(Conv1D(32, 3, activation='relu', input_shape=(220, 22)))
    model.add(Conv1D(32, 3, activation='relu'))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Dropout(0.25))

    model.add(Conv1D(64, 3, activation='relu'))
    model.add(Conv1D(64, 3, activation='relu'))
    model.add(MaxPooling1D(pool_size=2))
    model.add(Dropout(0.25))

    model.add(Flatten())
    model.add(Dense(256, activation='relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))

    sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
    model.compile(loss='binary_crossentropy', optimizer=sgd)

    model.fit(x_train, y_train, batch_size=30, epochs=150)
    # score = model.evaluate(x_test, y_test, batch_size=1)
    # print(score)
    num = 0
    y_pred = model.predict(x_test)
    for i in range(len(y_pred)):
        y_pred[i] = round(y_pred[i][0])
        if y_pred[i] == y_test[i]:
            num = num + 1
    acc = num / len(y_pred)
    print(model.summary())
    return acc

    # print(y_pred)
    # print(y_test)
    # score = classification_report(y_test, y_pred)
    # print(type(score))
    # print(score)


if __name__ == '__main__':
    # 入口
    X, Y = load_data()
    X = normailzed(X)
    X_0 = X[0:17].copy()
    X_1 = X[17:].copy()
    acc1 = 0
    acc2 = 0
    for i in range(100):
        print('第' + str(i) + '次循环开始')
        random.shuffle(X_0)  # 17
        random.shuffle(X_1)  # 26
        x_train = X_0[0:12] + X_1[0:18]
        y_train = [0] * 12 + [1] * 18
        x_test = X_0[12:] + X_1[18:]
        y_test = [0] * 5 + [1] * 8
        acc1 += MLP(x_train, y_train, x_test, y_test)
        acc2 += Conv_test(x_train, y_train, x_test, y_test)

    print(acc1 / 100)
    print(acc2 / 100)
